
var __yamb_stack = [];
var base = "/js/yamb/";

function Yamb(options) {
	options = $.extend({}, options);
	
	options.lang = options.language ? options.language.toLowerCase() : "en";
	
	// get game list
	if(typeof(options.games)=="undefined") {
		alert("Nothing to play.");
		return;
	}
	
	if(typeof(options.element)=="undefined") {
		alert("Please provide a valid destination HTML element");
	}
	
	// init Yamb Object
	this.object = $.extend(true, {}, YambObject);
	this.object.sex = typeof(options.sex)!="undefined" && options.sex.toLowerCase()=="female" ? "female" : "male";

	// load JS
	var libraries2load = [];
	libraries2load.push(root + base + 'array.lib.js');	
	libraries2load.push(root + base + 'string.lib.js');	
	for(var i=0; i<options.games.length; i++) {
		libraries2load.push(root + base + 'games/yamb.'+options.games[i]+'.js');	
	}
	libraries2load.push(root + base + 'lang/' + options.lang + '.js');
	options.element.html("loading yamb...");
	for(var i=0; i<libraries2load.length; i++) {
		this.object.loadScript(libraries2load[i]);
	}
	YambGo(libraries2load,this, options);
}
function YambGo(libraries2load, _this, options) {
	var loaded = true;
	for(var i=0; i<libraries2load.length; i++){
		if(typeof(_this.object.loadedScripts[libraries2load[i]])=="undefined") {
			loaded = false;
			unloaded = libraries2load[i];
			break;
		}
	}
	if(loaded) {
		_this.object.generateUUID();
		_this.object.multiplayer = options.multiplayer ? true : false;
		_this.object.loadGames(options.games);
		
		// draw interface
		_this.object.interface(options.element);
		
		// init games
		_this.object.initGames();
		
		__yamb_stack[_this.object.uuid] = _this;
	}else{
		var to = setTimeout(function(){
			YambGo(libraries2load, _this, options);
		}, 1000);
	}
}
function YambRestart(uuid, changeSex) {
	changeSex = changeSex ? true : false;
	var Y = __yamb_stack[uuid];
	if(typeof(Y)=="undefined") {
		return;
	}
	
	Y.object.holder.fadeOut({
		duration: 300,
		complete: function() {
			if(changeSex) {
				Y.object.sex = Y.object.sex=="male" ? "female" : "male";
				YambCookieSet("sex", Y.object.sex);
			}
			Y.object.holder.fadeIn({
				duration: 100,
				complete: function(){
					//Y.object.holder.empty();
					Y.object.interface(Y.object.holder);
					Y.object.initGames();
				}
			});
		}
	});
}
function YambHelp(uuid) {
	var h = $(".yamb-help");
	if(!h.length) {
		var _Y = __yamb_stack[uuid];
		if(!_Y) {
			return;
		}
		h = $('<div class="yamb-help" />');
		h.html("loading...");
		var container = _Y.object.holder.find(".yamb-container");
		container.prepend(h);
		var w = container.width() - parseInt(h.css("paddingLeft")) - parseInt(h.css("paddingRight"));
		h.css({
			width: w
		});
		$.ajax({
			url: root + base + "help.html",
			complete: function(req) {
				var close = $('<a href="javascript:void(0);" class="right yamb-help-close">close</a>');
				close.click(function(){
					h.slideUp("fast");
				});
				h.html(close);
				if(req.status == 200) {
					h.append(req.responseText);
				}else{
					h.append(req.status + ". " + req.statusText);
				}
			}
		});
	}
	if(h.is(":visible")) {
		h.slideUp("fast");
	}else{
		h.slideDown("fast");
	}
}
function YambCookieGet(name) {
	var nameEQ = "yamb_" + name + "=";
	var ca = document.cookie.split(';');
	for(var i=0;i < ca.length;i++) {
		var c = ca[i];
		while (c.charAt(0)==' ') c = c.substring(1,c.length);
		if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
	}
	return null;
}
function YambCookieSet(name, value) {
	document.cookie = "yamb_"+name+"="+escape(value)+"; path=/";
}

var YambObject = {
	uuid: "",
	holder: null,
	games: [],
	multiplayer: false,
	loadedScripts: {},
	sex: "male",
	
	table: null,
	dices: [],
	btn_throw: null,
	display: null,
	disp_countdown: null,
	btn_undo: null,
	btn_undo_html: '<a href="javascript:void(0)" class="undo">undo</a>',
	
	throwCount: 0,
	rolling: [0,0,0,0,0,0],
	countdown: 0,
	locked: true,
	interval: null,
	undoed: false,
	
	loadScript: function (url) {
		var _this = this;
		$.getScript(url, function(){
			_this.loadedScripts[url] = true;
		});
	},
	
	generateUUID: function() {
		var buffer = "qwertyuiopasdfghjklzxcvbnm1234567890";
		this.uuid = "";
		for(var i=0; i<10; i++) {
			this.uuid += buffer.substr(Math.random()*buffer.length, 1);
		}
	},
	loadGames: function(gameList) {
		for(var i=0; i<gameList.length; i++) {
			if(gameList[i]=="recall"){
				if(this.multiplayer) {
					this.games.push(gameList[i]);
				}
			}else{
				this.games.push(gameList[i]);
			}
			var game_object_name = "Yamb" + gameList[i].toTitleCase();
			eval("this." + game_object_name + " = $.extend(true,{},"+game_object_name+");");
			eval("this." + game_object_name + ".yamb = this;");
		}
	},
	initGames: function() {
		for(var i=0; i<this.games.length; i++) {
			var game_object_name = "Yamb" + this.games[i].toTitleCase();
			eval("this." + game_object_name + ".init();");
		}
	},
	interface: function(destination){
		var _Y = this;
		
		this.holder = destination;
		this.holder.empty();
		this.holder.mousedown(function(){return false;})
		
	// main interface
		var container = $('<div class="yamb-container" />');
		container.append('<a href="javascript:void(0)" class="right" onclick="YambHelp(\''+this.uuid+'\')">'+this._text("help").toTitleCase()+'</a>');
		container.append('<span class="right">&nbsp;&nbsp;|&nbsp;&nbsp;</span>');
		container.append('<a href="javascript:void(0)" class="right" title="'+this._text("change_sex")+'..." onclick="YambRestart(\''+this.uuid+'\', true)">Pol: '+this._text(this.sex=="male"?"for_male":"for_female").substr(0,1)+'</a>');
		container.append('<span class="right">&nbsp;&nbsp;|&nbsp;&nbsp;</span>');
		
		container.append('<div class="menu">' +
						 '<span>&#9660;'+this._text("new_game")+'</span>' + 
						 '<div class="submenu">' + 
						 '<a href="javascript:void(0)"onclick="YambRestart(\''+this.uuid+'\')">'+this._text("singleplayer")+'</a>' + 
						 '<a href="javascript:void(0)" href="">'+this._text("multiplayer")+'</a>' +
						 '</div>' +
						 '</div>');
		container.append('<h1 class="game-title">YAMB</h1>');
		container.append('<div class="yamb-table" />');
		this.holder.append(container);
		
	// table
		this.table = $('<table class="yamb" />');
		
	// table header
		tr = $('<tr class="head" />');
		tr.append('<td class="empty" />');
		for(i=0; i<this.games.length; i++) {
			tr.append('<td class="'+this.games[i]+'" style="background-image: url('+root+'/img/gui/column_'+this.games[i]+'.png)"></td>');
		}
		tr.append('<td class="empty" />');
		this.table.append(tr);
		
	// add table into page
		this.holder.find(".yamb-table").append(this.table);
		
	// 1-6 rows
		for(var i=0; i<6; i++) {
			this.makeRow(i+1);
		}
	// sum 1-6
		this.makeRow("sum1",true);
		
	// max/min
		this.makeRow("max");
		this.makeRow("min");
	// sum max/min
		this.makeRow("sum2",true);
		
	// big games
		this.makeRow("straight");
		this.makeRow("trilling");
		this.makeRow("full");
		this.makeRow("poker");
		this.makeRow("yamb");
	//sum big games
		this.makeRow("sum3",true);
		
	//total
		tr = $('<tr class="sum" />');
		for(i=0; i<(this.games.length+1); i++) {
			tr.append('<td class="empty" />');
		}
		tr.append('<td class="total yamb-total" />');
		this.table.append(tr);
	
	// control box
		var ctrlBox = $('<div class="controls" />');
		this.table.after(ctrlBox);

		//dices
			var dices = $('<ul class="dices" />');
			for(i=1; i<7; i++) {
				li = $('<li class="dice-'+i+'" value="0" />');
				li.click(function(){
					if(_Y.throwCount<3 && !_Y.isRolling()) {
						var numLocked = $(this).parent().find("li[locked=1]").length;
						if($(this).attr("value")) {
							locked = parseInt($(this).attr("locked")); locked = locked>0 ? 1 : 0;
							locked = numLocked<5 ? locked : 1;
							$(this).attr("locked",locked ? 0 : 1);
						}
					}
				});
				dices.append(li);
				this.dices[i] = li;
			}
			var totalFieldWidth = this.table.find(".total.yamb-total").width();
			ctrlBox.append(dices);
			ctrlBox.css({
				marginLeft: this.table.width() - totalFieldWidth
			});
			container.css("width", "auto");
			container.css("width", this.table.width() + ctrlBox.width() - totalFieldWidth);
			this.dices = dices;
		
		// clear
			ctrlBox.append('<br clear="all" />');
		
		// undo
			this.btn_undo = $(this.btn_undo_html);
			this.btn_undo.hide();
			ctrlBox.append(this.btn_undo);
				
		// display
			this.display = $('<div class="display">0</div>');
			ctrlBox.append(this.display);

		// throwButton
			this.btn_throw = $('<input type="button" value="'+this._text("throw")+'" class="throw-button" />');
			ctrlBox.append(this.btn_throw);
			
		// countdown
			this.countdown = 13 * this.games.length;
			this.disp_countdown = $('<div class="yamb-countdown" value="'+this.countdown+'">'+this.countdown+'</div>');
			ctrlBox.append(this.disp_countdown);
			ctrlBox.append('<div class="yamb-countdown-label">'+this._text("fields_left")+':</div>');
		
		this.throwCount = 3;
		this.init();
	},
	init: function() {
		var _Y = this;
		this.btn_throw.click(function(){
			_Y.locked = false;
			_Y.undo("hide");
			if(_Y.throwCount>0) {
				var _BTN = $(this);
				_BTN.attr("disabled","disabled");
				
				_Y.locked = true;
				_Y.rolling = [1,1,1,1,1,1];
				_Y.rollDice(0);
				_Y.interval = setInterval(function(){
					if(!_Y.isRolling()) {
						clearInterval(_Y.interval);
						_BTN.attr("disabled",false);
						_Y.interval = null;					
						_Y.throwCount--;
						_Y.locked = false;
						_Y.holder.find(".display").html(3-_Y.throwCount);
						
						// trigger onRollDice event for every game
						for(var i=0; i<_Y.games.length; i++) {
							game_object_name = "Yamb" + _Y.games[i].toTitleCase();
							var obj = eval("_Y." + game_object_name);
							if(obj.onRollDice) {
								obj.onRollDice();
							}
						}
					}
				}, 100);
			}
		});
	},
	makeRow: function(rowGame, isSum) {
		var _Y = this;
		isSum = isSum ? true : false;
		
		var tr = $('<tr class="'+(isSum?"sum":"")+'" game="'+rowGame+'" />');
		tr.append('<td class="label">'+this._text(rowGame)+'</td>');
		for(var i=0; i<this.games.length; i++) {
			td = $('<td game_row="'+(rowGame)+'" game_column="'+this.games[i]+'"'+(isSum?'':' class="field"')+(isSum?'':' locked="0"')+' />');
			if(!isSum) {
				// set field-click event
				td.click(function(){_Y.fieldClick($(this))});
				td.mouseover(function(){
					if(!_Y.locked && $(this).hasClass("toplay")) {
						$(this).addClass("over-value");
						var val = _Y.getGameValue(rowGame);
						$(this).html(val)
					}
				});
				td.mouseout(function(){
					if(!$(this).hasClass("played")) {
						$(this).removeClass("over-value");
						$(this).html("");
					}
				});
				td.click(function(){
					if(!$(this).hasClass("toplay")) {
						$(this).removeClass("over-value");
					}
				});
			}
			tr.append(td);
		}
		tr.append('<td class="'+(isSum?"total":"empty")+'" />');
		this.table.append(tr);
	},
	fieldClick: function(td) {
		if(!this.locked) {
			var obj_name = "Yamb" + td.attr("game_column").toTitleCase();
			obj = eval("this." + obj_name);
			if(typeof obj != "undefined") {
				if(typeof obj.play != "undefined") {
					if( obj.play(td) ) {
						// reset game data
						this.locked = true;
						this.undo("show", td);
						this.dices.find("li").attr("locked", 0);
						this.throwCount = 3;
						this.holder.find(".display").html(0);
						this.countdown--;
						this.holder.find(".yamb-countdown").attr("value", this.countdown).html(this.countdown);
						this.updateSum(td);
						this.undoed = false;
						
						if(this.countdown<1) {
							this.end();
						}
					}
				}else{
					alert("Object " + obj_name + " doesn't support PLAY method.");
				}
			}else{
				alert("Object " + obj_name + " not found.");
			}
		}
	},
	isRolling: function() {
		var ret = false;
		for(var i=0; i<this.rolling.length; i++) {
			if(this.rolling[i]) {
				ret = true;
				break;
			}
		}
		return ret;
	},
	rollDice: function(index) {
		index = index>0?index:0;
		dice = this.holder.find("ul.dices li").eq(index);
		locked = parseInt(dice.attr("locked")); locked = locked>0 ? true : false;
		if(!locked) {
			var spins = Math.floor(Math.random()*5) + 1;
			this._roll(index,dice,spins,0);
		}else{
			this.rolling[index] = 0;
		}
		if(index<5) {
			this.rollDice(index+1);
		}
	},
	_roll: function(index, dice, spins, spin) {
		var _Y = this;
		if(spin<spins) {
			tmp = Math.floor(Math.random()*6) + 1;
			dice.attr("class","");
			dice.addClass("dice-"+(index+1));
			dice.addClass("value"+tmp);
			dice.attr("value",tmp);
			setTimeout(function(){
				_Y._roll(index, dice, spins, spin+1);
			}, 200);
		}else{
			_Y.rolling[index] = 0;
		}
	},
	undo: function(action, td) {
		var _Y = this;
		_Y.btn_undo.remove();
		
		var FieldsLeft = parseInt(_Y.countdown);
		
		if(action == "show" && FieldsLeft>0) {			
			var game_object_name = "Yamb" + td.attr("game_column").toTitleCase();
			GameObject = eval("_Y." + game_object_name);
			
			if(GameObject.cantUndo === true) {
				return;
			}
			
			_Y.btn_undo = $(_Y.btn_undo_html);
			_Y.btn_undo.html(_Y._text("undo"));
			_Y.display.before(_Y.btn_undo);
			
			_Y.btn_undo.show();
			_Y.btn_undo.click(function(){
				GameObject.undo(td);
				_Y.undoed = true;
				td.html("");
				td.removeAttr("value");
				_Y.throwCount = 0;
				_Y.updateSum(td);
				_Y.holder.find(".display").html(3);
				_Y.countdown++;
				_Y.holder.find(".yamb-countdown").html(_Y.countdown);
				_Y.locked = false;
				_Y.undo("hide");
			});
		}
	},
	toPlay: function(td) {
		return td.hasClass("toplay");
	},
	getDices: function(justSelected) {
		justSelected = justSelected ? true : false;
		var dices = [0,0,0,0,0,0];
		this.dices.find("li").each(function(index){
			if(parseInt($(this).attr("locked"))>0) {
				dices[index] = parseInt($(this).attr("value"));
			}
		});
		if(justSelected) {
			tmp = [];
			for(x in dices) {
				if(dices[x] > 0) {
					tmp.push(dices[x]);
				}
			}
			dices = tmp;
		}
		return dices;
	},
	getGameValue: function(row_game) {
		row_game = "" + row_game;
		var value = 0;
		var dices = this.getDices();
		switch(row_game.toLowerCase()) {
			case "1":
			case "2":
			case "3":
			case "4":
			case "5":
			case "6":
				for(x in dices) {
					if(parseInt(dices[x]) == parseInt(row_game)) {
						value += parseInt(row_game);
					}
				}
				break;
			case "max":
				value = dices.sum();
				break;
			case "min":
				var selected = this.dices.find("li[locked=1]").length;
				if(selected==5) {
					value = dices.sum();
				}else{
					value = 30;
				}
				break;
			case "straight":
				dices = this.getDices(true).sort();
				var straight = false;
				if(dices.length==5) {
					straight = true;
					for(var i=1; i<dices.length; i++) {
						if(dices[i]==dices[i-1] || (dices[i]-dices[i-1])!=1) {
							straight=false;
							break;
						}
					}
				}
				if(straight) {
					value = 66 - (3 - this.throwCount -1)*10;
				}else{
					value = 0;
				}
				break;
			case "trilling":
				value = this.getDices().sum2(3);
				value = value>0 ? 20+value : 0;
				break;
			case "full":
				sum = this.getDices().sum2();
				it_3 = 0;
				it_2 = 0;
				for(x in sum) {
					if(sum[x]>=3) {
						it_3 = x;
						sum[x] -= 3
					}
				}
				for(x in sum) {
					if(sum[x]==2) {
						it_2 = x;
					}
				}
				if(it_2>0 && it_3>0) {
					value = 30 + 3*it_3 + 2*it_2;
				}else{
					value = 0;
				}
				break;
			case "poker":
				value = this.getDices().sum2(4);
				value = value>0 ? value+40 : 0;
				break;
			case "yamb":
				value = this.getDices().sum2(5);
				value = value>0 ? value+50 : 0;
				break;
		}
		return value;
	},
	updateSum: function(td) {
		if(td) {
			var game_column = td.attr("game_column");
			var sumRow=td.parent().next();
			while(sumRow.length && !sumRow.hasClass("sum")) {
				sumRow = sumRow.next();
			}
			var isFirst = td.attr("game_row")=="1" ? true : false;
			if(sumRow.length) {
				var sumColumn = sumRow.find("td[game_column="+game_column+"]");
				var sum = 0; var val;
				var sum_row = sumColumn.attr("game_row");
				switch(sum_row) {
					case "sum1":
					case "sum3":
						var prevField = sumRow.prev().find("td.field[game_column="+game_column+"]").eq(0);
						while(prevField.hasClass("field")) {
							val = parseInt(prevField.html());
							val = val>0 ? val : 0;
							sum += val;
							prevField = prevField.parent().prev().find("td.field[game_column="+game_column+"]").eq(0);
						}
						sum = (sum_row=="sum1") ? (sum>=60 ? sum+30 : sum) : sum;
						sumColumn.html(sum).attr("value",sum);
						if(!isFirst) {
							break;
						}
						sumColumn = this.table.find("td[game_row=sum2][game_column="+game_column+"]");
					case "sum2":
						
						var first = parseInt(this.table.find("td.field[game_row=1][game_column="+game_column+"]").html());
						var max = parseInt(this.table.find("td.field[game_row=max][game_column="+game_column+"]").html());
						var min = parseInt(this.table.find("td.field[game_row=min][game_column="+game_column+"]").html());
						
						first = first>0 ? first : 0;
						max  = max>0 ? (min>0 ? max : 0) : 0;
						min = min>0 ? min : 0;
						
						sum = first * (max-min); sum = sum>0 ? sum : 0;
						sumColumn.html(sum).attr("value",sum);
						break;
				}
			}
			var total=0, total_1, total_2;
			
			this.table.find("tr.sum").each(function(){
				total_1 = 0;
				$(this).find("td[game_column]").each(function(){
					total_2 = parseInt($(this).html()); total_2 = total_2>0 ? total_2 : 0;
					total_1 += total_2;
				});
				total += total_1;
				$(this).find("td.total").html(total_1);
			});
			this.table.find(".yamb-total").html(total);
		}
	},
	end: function() {
		var total = parseInt(this.holder.find(".yamb-total").html());
		var destination = this.holder.find(".yamb-container").eq(0);
		
		var mask = $('<div id="yamb-end-mask" />');
		
		var h = destination.height();
		var paddingTop = parseInt(destination.css("padding-top"));
		var paddingBottom = parseInt(destination.css("padding-bottom"));
		h += (paddingTop>0?paddingTop:0) + (paddingBottom>0?paddingBottom:0);
		
		var w = destination.width();
		var paddingLeft = parseInt(destination.css("padding-left"));
		var paddingRight = parseInt(destination.css("padding-right"));
		w += (paddingLeft>0?paddingLeft:0) + (paddingRight>0?paddingRight:0);
		
		mask.css({
			height: h,
			opacity: 0.6
		});
		destination.prepend(mask);
		
		var container = $('<div id="yamb-end-container" />');
		var html = '<h2>'+this._text("game_end")+'</h2>';
		html += '<p><strong>'+this._text("result")+': <span class="end-result">'+total+'</span></strong></p>';
		html += '<p><a href="javascript:void(0)" onclick="YambRestart(\''+this.uuid+'\');">'+this._text("new_game")+'</a></p>';
		container.html(html);
		container.hide();
		destination.prepend(container);
		container.css({
			left: (w-container.width())/2,
			top: (h-container.height())/2
		});
		container.fadeIn("slow");
		
		
	},
	_text: function (str) {
		if(typeof YAMB_TEXT[str] == "undefined") {
			return str;
		}else{
			return YAMB_TEXT[str];
		}
	}
};